package com.demo.scenic.service.impl;

import com.demo.scenic.common.BaseResponse;
import com.demo.scenic.domain.*;
import com.demo.scenic.domain.vo.ScenicNameVo;
import com.demo.scenic.domain.vo.ScenicVo;
import com.demo.scenic.mapper.*;
import com.demo.scenic.service.BusinessService;
import com.demo.scenic.shiro.AccountProfile;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;


@Service
@AllArgsConstructor
public class BusinessServiceImpl implements BusinessService {

    private final ScenicBaseMapper scenicBaseMapper;
    private final ScenicPhotoMapper scenicPhotoMapper;

    private final ScenicOtherMapper scenicOtherMapper;

    private final UserMapper userMapper;

    private final UserRoleMapper userRoleMapper;
    private final RoleMapper roleMapper;
    private final TimeConfigMapper timeConfigMapper;

    private final TicketTypeMapper ticketTypeMapper;

    private final TimePeriodMapper timePeriodMapper;

    private final ScenicActivityMapper scenicActivityMapper;

    private final BookedRecordMapper bookedRecordMapper;

    private final ScenicImgMapper scenicImgMapper;

    private final Logger logger = LoggerFactory.getLogger(BusinessServiceImpl.class);

    @Override
    public BaseResponse getScenic(AccountProfile accountProfile) {
        User user = userMapper.selectByPrimaryKey(accountProfile.getId());
        ScenicBaseExample scenicBaseExample = new ScenicBaseExample();
        UserRoleExample userRoleExample = new UserRoleExample();
        userRoleExample.createCriteria().andUserIdEqualTo(accountProfile.getId());
        Role role = roleMapper.selectByPrimaryKey(userRoleMapper.selectByExample(userRoleExample).get(0).getRoleId());
        if (role.getRoleName().equals("ADMIN")){
            scenicBaseExample.createCriteria().andIsDeleteEqualTo(true);
        } else {
            if (ObjectUtils.isNotEmpty(user.getScenicId())){
                scenicBaseExample.createCriteria().andIsDeleteEqualTo(true).andIdEqualTo(user.getScenicId());
            }
        }
        List<ScenicBase> scenicBases = scenicBaseMapper.selectByExample(scenicBaseExample);
        List<ScenicVo> scenicVoList = new ArrayList<>();
        for (ScenicBase scenicBase : scenicBases){
            ScenicVo scenicVo = new ScenicVo();
            scenicVo.setScenicBase(scenicBase);
            scenicVo.setScenicOther(getScenicOther(scenicBase.getId()));
            scenicVo.setScenicPhotos(getScenicImage(scenicBase.getId()));
            scenicVo.setTimeConfig(getScenicTime(scenicBase.getId()));
            scenicVo.setScenicImgList(getScenicImg(scenicBase.getId()));
            scenicVoList.add(scenicVo);
        }
        return BaseResponse.ok(scenicVoList);
    }

    @Override
    public BaseResponse getScenicNames() {
        ScenicBaseExample scenicBaseExample = new ScenicBaseExample();
        scenicBaseExample.createCriteria().andIsDeleteEqualTo(true);
        List<ScenicNameVo> scenicNameVoList = new ArrayList<>();
        List<ScenicBase> scenicBases = scenicBaseMapper.selectByExample(scenicBaseExample);
        for (ScenicBase base : scenicBases) {
            ScenicNameVo scenicNameVo = new ScenicNameVo();
            BeanUtils.copyProperties(base,scenicNameVo);
            scenicNameVoList.add(scenicNameVo);
        }
        return BaseResponse.ok(scenicNameVoList);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse addScenicBase(ScenicBase scenicBase) {
        if (ObjectUtils.isEmpty(scenicBase.getStopEntryTime())){
            scenicBase.setStopEntryTime(scenicBase.getEndTime());
        }
        int judge = scenicBaseMapper.insertSelective(scenicBase);
        if (judge > 0){
            return BaseResponse.ok("新增景区基本信息成功");
        }
        return BaseResponse.fail("新增景区基本信息失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse updateScenicBase(ScenicBase scenicBase) {
        int judge = scenicBaseMapper.updateByPrimaryKeySelective(scenicBase);
        if (judge > 0){
            return BaseResponse.ok("修改景区基本信息成功");
        }
        return BaseResponse.fail("修改景区基本信息失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse deleteScenicBase(Integer id) {
        ScenicBase scenicBase = scenicBaseMapper.selectByPrimaryKey(id);
        scenicBase.setIsDelete(false);
        int judge = scenicBaseMapper.updateByPrimaryKeySelective(scenicBase);
        if (judge > 0){
            return BaseResponse.ok("删除景区基本信息成功");
        }
        return BaseResponse.fail("删除景区基本信息失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse bindScenic(AccountProfile accountProfile, Integer scenicId) {
        User user = userMapper.selectByPrimaryKey(accountProfile.getId());
        user.setScenicId(scenicId);
        int judge = userMapper.updateByPrimaryKey(user);
        if (judge > 0){
            return BaseResponse.ok("绑定景区成功");
        }
        return BaseResponse.fail("绑定景区失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse addScenicImage(ScenicPhoto scenicPhoto) {
        int judge = scenicPhotoMapper.insertSelective(scenicPhoto);
        if (judge > 0){
            return BaseResponse.ok("新增景区宣传图成功");
        }
        return BaseResponse.fail("新增景区宣传图失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse updateScenicImage(ScenicPhoto scenicPhoto) {
        int judge = scenicPhotoMapper.updateByPrimaryKeySelective(scenicPhoto);
        if (judge > 0){
            return BaseResponse.ok("修改景区宣传图成功");
        }
        return BaseResponse.fail("修改景区宣传图失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse deleteScenicImage(Integer id) {
        int judge = scenicPhotoMapper.deleteByPrimaryKey(id);
        if (judge > 0){
            return BaseResponse.ok("删除景区宣传图成功");
        }
        return BaseResponse.fail("删除景区宣传图失败");
    }

    @Override
    public List<ScenicPhoto> getScenicImage(Integer scenicId) {
        ScenicPhotoExample scenicPhotoExample = new ScenicPhotoExample();
        scenicPhotoExample.createCriteria().andScenicIdEqualTo(scenicId);
        return scenicPhotoMapper.selectByExample(scenicPhotoExample);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse addScenicOther(ScenicOther scenicOther) {
        int judge = scenicOtherMapper.insertSelective(scenicOther);
        if (judge > 0){
            return BaseResponse.ok("新增景区信息成功");
        }
        return BaseResponse.fail("新增景区信息失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse updateScenicOther(ScenicOther scenicOther) {
        int judge = scenicOtherMapper.updateByPrimaryKeySelective(scenicOther);
        if (judge > 0){
            return BaseResponse.ok("修改景区信息成功");
        }
        return BaseResponse.fail("修改景区信息失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse deleteScenicOther(Integer id) {
        ScenicOtherExample scenicOtherExample = new ScenicOtherExample();
        scenicOtherExample.createCriteria().andScenicIdEqualTo(id);
        ScenicOther scenicOther = scenicOtherMapper.selectByExample(scenicOtherExample).get(0);
        scenicOther.setIsDelete(true);
        int judge = scenicOtherMapper.updateByPrimaryKeySelective(scenicOther);
        if (judge > 0){
            return BaseResponse.ok("删除景区信息成功");
        }
        return BaseResponse.fail("删除景区信息失败");
    }

    @Override
    public ScenicOther getScenicOther(Integer scenicId) {
        ScenicOtherExample scenicOtherExample = new ScenicOtherExample();
        scenicOtherExample.createCriteria().andIsDeleteEqualTo(true).andScenicIdEqualTo(scenicId);
        List<ScenicOther> scenicOthers = scenicOtherMapper.selectByExample(scenicOtherExample);
        if (scenicOthers.size() > 0){
            return scenicOthers.get(0);
        }
        return null;
    }


    @Override
    public TimeConfig getScenicTime(Integer scenicId) {
       TimeConfig timeConfigs = timeConfigMapper.selectByScenicId(scenicId);
        return timeConfigs;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse addTicketType(TicketType ticketType) {
        int judge = ticketTypeMapper.insertSelective(ticketType);

        if (judge > 0){
            return BaseResponse.ok("新增门票类型成功");
        }
        return BaseResponse.fail("新增门票类型失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse updateTicketType(TicketType ticketType) {
        int judge = ticketTypeMapper.updateByPrimaryKeySelective(ticketType);
        if (judge > 0){
            return BaseResponse.ok("修改门票类型成功");
        }
        return BaseResponse.fail("修改门票类型失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse updateTicketStatus(Integer id) {
        TicketType ticketType = ticketTypeMapper.selectByPrimaryKey(id);
        ticketType.setIsEnable(!ticketType.getIsEnable());
        int judge = ticketTypeMapper.updateByPrimaryKeySelective(ticketType);
        if (judge > 0){
            return BaseResponse.ok("修改门票状态成功");
        }
        return BaseResponse.fail("修改门票状态失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse deleteTicketType(Integer id) {
        TicketType ticketType = ticketTypeMapper.selectByPrimaryKey(id);
        ticketType.setIsDelete(false);
        int judge = ticketTypeMapper.updateByPrimaryKeySelective(ticketType);
        if (judge > 0){
            return BaseResponse.ok("删除门票类型成功");
        }
        return BaseResponse.fail("删除门票类型失败");
    }

    @Override
    public BaseResponse getTicketType(Integer scenicId) {
        TicketTypeExample ticketTypeExample = new TicketTypeExample();
        ticketTypeExample.createCriteria().andIsDeleteEqualTo(true).andScenicIdEqualTo(scenicId);
        List<TicketType> ticketTypes = ticketTypeMapper.selectByExample(ticketTypeExample);
        return BaseResponse.ok(ticketTypes);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse addTimeConfig(TimeConfig timeConfig) {
        ScenicBase scenicBase = scenicBaseMapper.selectByPrimaryKey(timeConfig.getScenicId());
        TimeConfig demo = timeConfigMapper.selectByPrimaryKey(timeConfig.getId());
        if (ObjectUtils.isEmpty(demo)){
            timeConfigMapper.insertSelective(timeConfig);
        } else {
            timeConfigMapper.updateByPrimaryKeySelective(timeConfig);
        }
        LocalTime startTime = LocalTime.parse(scenicBase.getStartTime(), DateTimeFormatter.ofPattern("HH:mm"));
        LocalTime endTime = LocalTime.parse(scenicBase.getEndTime(), DateTimeFormatter.ofPattern("HH:mm"));
        LocalTime stopEntryTime = LocalTime.parse(scenicBase.getStopEntryTime(), DateTimeFormatter.ofPattern("HH:mm"));
        if (stopEntryTime.compareTo(endTime) < 0){
            endTime = stopEntryTime;
        }
        int count = 0;
        List<String> times = getTimes(startTime, endTime, timeConfig.getIntervalNums());
        for (String time : times) {
            TimePeriod timePeriod = new TimePeriod();
            timePeriod.setScenicId(timeConfig.getScenicId());
            timePeriod.setTimePeriod(time);
            count += timePeriodMapper.insertSelective(timePeriod);
        }
        if (count == times.size() && count > 0){
            return BaseResponse.ok("设置时间配置成功");
        }
        return BaseResponse.fail("设置时间配置失败");
    }
    public static List<String> getTimes(LocalTime start, LocalTime end, int intervalNums) {
        List<String> times = new ArrayList<>();
        // 循环输出时间段
        while (start.plusMinutes(intervalNums).isBefore(end) || start.plusMinutes(intervalNums).equals(end)) {
            if (start.equals(end)||start.isAfter(end))
                break;
            times.add(start + "-" + start.plusMinutes(intervalNums));
            start = start.plusMinutes(intervalNums);
        }
        return times;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse updateTimeConfig(TimeConfig timeConfig) {
        TimePeriodExample timePeriodExample = new TimePeriodExample();
        timePeriodExample.createCriteria().andScenicIdEqualTo(timeConfig.getScenicId());
        timePeriodMapper.deleteByExample(timePeriodExample);
        return addTimeConfig(timeConfig);
    }



    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse addScenicActivity(ScenicActivity scenicActivity) {
        int judge = scenicActivityMapper.insertSelective(scenicActivity);
        if (judge > 0){
            return BaseResponse.ok("新增景区活动成功");
        }
        return BaseResponse.fail("新增景区活动失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse updateScenicActivity(ScenicActivity scenicActivity) {
        int judge = scenicActivityMapper.updateByPrimaryKeySelective(scenicActivity);
        if (judge > 0){
            return BaseResponse.ok("修改景区活动成功");
        }
        return BaseResponse.fail("修改景区活动失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse deleteScenicActivity(Integer id) {
        ScenicActivity scenicActivity = scenicActivityMapper.selectByPrimaryKey(id);
        scenicActivity.setIsDelete(false);
        int judge = scenicActivityMapper.updateByPrimaryKeySelective(scenicActivity);
        if (judge > 0){
            return BaseResponse.ok("删除景区活动成功");
        }
        return BaseResponse.fail("删除景区活动失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse updateScenicActivityStatus(Integer id) {
        ScenicActivity scenicActivity = scenicActivityMapper.selectByPrimaryKey(id);
        scenicActivity.setIsEnable(!scenicActivity.getIsEnable());
        int judge = scenicActivityMapper.updateByPrimaryKeySelective(scenicActivity);
        if (judge > 0){
            return BaseResponse.ok("修改景区活动状态成功");
        }
        return BaseResponse.fail("修改景区活动状态失败");
    }

    @Override
    public List<ScenicActivity> getScenicActivity(Integer scenicId) {
        ScenicActivityExample scenicActivityExample = new ScenicActivityExample();
        scenicActivityExample.createCriteria().andScenicIdEqualTo(scenicId).andIsDeleteEqualTo(true);
        return scenicActivityMapper.selectByExample(scenicActivityExample);
    }

    @Override
    public List<TimePeriod> getTimePeriod(Integer scenicId) {
        TimePeriodExample timePeriodExample = new TimePeriodExample();
        timePeriodExample.createCriteria().andScenicIdEqualTo(scenicId);
        return timePeriodMapper.selectByExample(timePeriodExample);
    }

    @Override
    public BaseResponse getScenicOrder(Integer scenicId) {
        BookedRecordExample bookedRecordExample = new BookedRecordExample();
        bookedRecordExample.createCriteria().andScenicIdEqualTo(scenicId);
        bookedRecordExample.setOrderByClause("booked_date desc");
        List<BookedRecord> bookedRecords = bookedRecordMapper.selectByExample(bookedRecordExample);
        return BaseResponse.ok(bookedRecords);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse addScenicImg(ScenicImg scenicImg) {
        int judge = scenicImgMapper.insertSelective(scenicImg);
        if (judge > 0){
            return BaseResponse.ok("新增景区介绍图成功");
        }
        return BaseResponse.fail("新增景区介绍图失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse updateScenicImg(ScenicImg scenicImg) {
        int judge = scenicImgMapper.updateByPrimaryKeySelective(scenicImg);
        if (judge > 0){
            return BaseResponse.ok("修改景区介绍图成功");
        }
        return BaseResponse.fail("修改景区介绍图失败");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class, isolation = Isolation.READ_COMMITTED)
    public BaseResponse deleteScenicImg(Integer id) {
        ScenicImg scenicImg = scenicImgMapper.selectByPrimaryKey(id);
        scenicImg.setIsDelete(false);
        int judge = scenicImgMapper.updateByPrimaryKeySelective(scenicImg);
        if (judge > 0){
            return BaseResponse.ok("删除景区介绍图成功");
        }
        return BaseResponse.fail("删除景区介绍图失败");
    }

    @Override
    public List<ScenicImg> getScenicImg(Integer scenicId) {
        ScenicImgExample scenicImgExample = new ScenicImgExample();
        scenicImgExample.createCriteria().andScenicIdEqualTo(scenicId).andIsDeleteEqualTo(true);
        return scenicImgMapper.selectByExample(scenicImgExample);
    }
}
